package brainsplash.gyrusscope.game;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.util.Log;
import brainsplash.gyrusscope.framework.gl.TextureRegion;
import brainsplash.gyrusscope.framework.math.OverlapTester;
import brainsplash.gyrusscope.framework.math.Vector2;

public class World {

	public int timeElapsed = 0;
	public boolean running = false;
	public float viewScale = 1.0f;
	//public ArrayList<Orig_GameObject> gameObjects = new ArrayList();
	public ArrayList<Spaceship> spaceships = new ArrayList<Spaceship>();
	public ArrayList<Blast> blasts = new ArrayList<Blast>();
	public ArrayList<Asteroid> asteroids = new ArrayList<Asteroid>();
	public ArrayList<Explosion> explosions = new ArrayList<Explosion>();
	//public ArrayList<Level> levels = new ArrayList();
	public Player player;
	//public int levelIndex = 0;
	//public Level level = new Level();
	public int[] alarm = {0, 0, 0};
	public int enemyspawn = 0;
	public int score;
	public final static float firingAngleThreshhold = 30; //max angle at which the AI will fire
	public final static float firingLikelihood = 0.6f; //percent chance of firing if able
	public Random randomGenerator = new Random(); //So that AI fires somewhat randomly
	public float enemyoffset = 0;
    public static final float WORLD_WIDTH = 1000;
    public static final float WORLD_HEIGHT = 150 * 200;
    public static final int WORLD_STATE_RUNNING = 0;
    public static final int WORLD_STATE_NEXT_LEVEL = 1;
    public static final int WORLD_STATE_GAME_OVER = 2;
    
    //public final WorldListener listener;
    public final Random rand;
    

    public float heightSoFar;
    public int state;

    public World() {//WorldListener listener) {
    	//Log.d(">>>>>>>", "World Started");
        rand = new Random();
        
        Level.currentWave = 0;
        Level.waveCounter = 0;
        this.heightSoFar = 0;
        this.score = 0;
        this.state = WORLD_STATE_RUNNING;
        
    	// Initialization
    	player = new Player(Assets.humanship, 2, 2, 20, 100, -90, 0);
    	spaceships.add(player);
    	//gameObjects.add(player);
    	//level = levels.get(levelIndex);

        //generateLevel();

    }
    
	private void levelAction() {
		Level.waveCounter += 1;
		Level.currentWave += 1;
		Level.currentWave %= Level.waves.length;
		enemyspawn = 0;
		enemyoffset = randomGenerator.nextFloat() * 360f;
	}
	
	private void spawnEnemy() {
		if (enemyspawn < Level.waves[Level.currentWave][0]) {
			spaceships.add(new Enemy(Level.enemyTypes[Level.waves[Level.currentWave][1]], 1, 1, 20, Level.wavePaths[Level.currentWave], enemyoffset));
			enemyspawn += 1;
		}
	}

	public void update(float deltaTime) {
		//Log.d(">>>>>>>", "Updated");
	    // Game Processing
		alarm[0] += 1;
		alarm[1] += 1;
		if (alarm[0] >= Math.max(Level.waveSpawnIntervals[Level.currentWave] - Level.waveCounter * 15, 60)) {levelAction(); alarm[0] = 0;}
		if (alarm[1] >= 20) {spawnEnemy(); alarm[1] = 0;}
		if (randomGenerator.nextFloat() <= 0.001 * Level.waveCounter) {
			asteroids.add(new Asteroid(Assets.asteroid, 0, 0, (int) (15 + 10 * randomGenerator.nextFloat()), 15,  randomGenerator.nextFloat() * 360f, -1, 50));
		}
		
		//Move and update screen
		for (int i = 0; i < spaceships.size(); i++) {
			spaceships.get(i).update();
		}
		for (int i=0; i < blasts.size(); i++) {
			blasts.get(i).update();
		}
		for (int i=0; i < asteroids.size(); i++) {
			asteroids.get(i).update();
		}
		for (int i=0; i < explosions.size(); i++) {
			explosions.get(i).update();
		}
		
	
		//After moving attempt to fire and check for collisions
		for (int i = 0; i < spaceships.size(); i++) {
			Spaceship s = spaceships.get(i);
			s.reloadCounter += 1;
			if (s instanceof Enemy) {
				if (Math.abs(player.direction-s.direction) % (360) < firingAngleThreshhold && ((Enemy) s).canAttack
						&& (s.distanceFromCenter > player.distanceFromCenter || s.speed < 0) && s.reload <= s.reloadCounter) {
					if (randomGenerator.nextFloat() <= firingLikelihood) {
						blasts.addAll(s.fire(Math.round(randomGenerator.nextFloat())));
						s.reloadCounter = 0;
						//Log.d(">>>>>>>", "Shots fired");
					}
				}
			}
	    	for (int j = 0; j < blasts.size(); j++) {
	    		Blast b = blasts.get(j);
				int coll = b.collisionWith(s);
				if (coll == 1) {blasts.remove(b);}
				else if (coll == 2) {
					blasts.remove(b); 
					spaceships.remove(s);
					int count = randomGenerator.nextInt(2) + 1; //will always have at least one explosion
					for (int k = 0; k < count; k++) {
						float distOffset = (randomGenerator.nextFloat() * s.distanceFromCenter/4) - s.distanceFromCenter/8;
						float dirOffset = (randomGenerator.nextFloat() * 5) - 2.5f;
						explosions.add(new Explosion(Assets.explosion, s.x, s.y, s.radius, s.distanceFromCenter + distOffset, s.direction + dirOffset, -2, 0.5f));
					}
					
					//randomGenerator.nextFloat() * 360f;
					explosions.add(new Explosion(Assets.explosion, s.x, s.y, s.radius, s.distanceFromCenter, s.direction, -2, 0.3f));
					Assets.playSound(Assets.explodeSound, 0.25f);
					
					if (s instanceof Enemy) {score += 100;}
				}
				
				if (b.distanceFromCenter == 10) {
					blasts.remove(b);
				}
			}
		}
		
		for (int i = 0; i < asteroids.size(); i++) {
			Asteroid a = asteroids.get(i);
	    	for (int j = 0; j < blasts.size(); j++) {
	    		Blast b = blasts.get(j);
				int coll = b.collisionWith(a);
				if (coll == 1) {blasts.remove(b);}
				else if (coll == 2) {
					blasts.remove(b); 
					asteroids.remove(a);
					int count = randomGenerator.nextInt(2) + 1; //will always have at least one explosion
					for (int k = 0; k < count; k++) {
						float distOffset = (randomGenerator.nextFloat() * a.distanceFromCenter/4) - a.distanceFromCenter/8;
						float dirOffset = (randomGenerator.nextFloat() * 5) - 2.5f;
						explosions.add(new Explosion(Assets.explosion, a.x, a.y, a.radius, a.distanceFromCenter + distOffset, a.direction + dirOffset, -2, 0.5f));
					}
					
					//randomGenerator.nextFloat() * 360f;
					explosions.add(new Explosion(Assets.explosion, a.x, a.y, a.radius, a.distanceFromCenter, a.direction, -2, 0.3f));
					Assets.playSound(Assets.explodeSound, 0.25f);
				}
	    	}
	    	
			int coll = a.collisionWith(player);
			if (coll == 1) {asteroids.remove(a);}
			else if (coll == 2) {
				spaceships.remove(player); 
				asteroids.remove(a);
			}
			
			if (coll > 0) {
				int count = randomGenerator.nextInt(2) + 1; //will always have at least one explosion
				for (int k = 0; k < count; k++) {
					float distOffset = (randomGenerator.nextFloat() * a.distanceFromCenter/4) - a.distanceFromCenter/8;
					float dirOffset = (randomGenerator.nextFloat() * 5) - 2.5f;
					explosions.add(new Explosion(Assets.explosion, a.x, a.y, a.radius, a.distanceFromCenter + distOffset, a.direction + dirOffset, -2, 0.5f));
				}
				
				//randomGenerator.nextFloat() * 360f;
				explosions.add(new Explosion(Assets.explosion, a.x, a.y, a.radius, a.distanceFromCenter, a.direction, -2, 0.3f));
				Assets.playSound(Assets.explodeSound, 0.25f);
			}
		}
		
		for (int i = 0; i < explosions.size(); i++) {
			Explosion e = explosions.get(i);
			e.duration -= deltaTime;
			if (e.duration <= 0) {
				explosions.remove(e);
			}
		}
		
	    checkGameOver();
	}

    private void checkGameOver() {
        if (!spaceships.contains(player)) {
        	state = WORLD_STATE_GAME_OVER;
        }
    }
}